package com.fs.robot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.api.client.AlertClient;
import com.fs.api.domain.vo.AlertDetailVO;
import com.fs.api.domain.vo.RobotVO;
import com.fs.api.enumeration.AlertStatus;
import com.fs.api.enumeration.RobotStatus;
import com.fs.common.domain.PageVO;
import com.fs.common.domain.Result;
import com.fs.common.exception.BusinessException;
import com.fs.common.utils.BeanUtils;
import com.fs.common.utils.CollUtils;
import com.fs.robot.domain.dto.RobotCreateDTO;
import com.fs.robot.domain.po.Robot;
import com.fs.robot.domain.vo.BatteryDistributionVO;
import com.fs.robot.domain.vo.RobotDetailVO;
import com.fs.robot.domain.vo.RobotOverviewVO;
import com.fs.robot.domain.vo.RobotStatusDistributionVO;
import com.fs.robot.mapper.RobotMapper;
import com.fs.robot.service.IRobotService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.fs.api.enumeration.AlertStatus.PROCESSING;
import static com.fs.api.enumeration.RobotStatus.IDLE;
import static com.fs.common.enumeration.BusinessExceptionEnum.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class RobotServiceImpl extends ServiceImpl<RobotMapper, Robot> implements IRobotService {
    private final RobotMapper robotMapper;
    private final AlertClient alertClient;

    @Override
    public PageVO<RobotVO> getRobotsPage(Integer pageNum, Integer pageSize) {
        Page<Robot> page = lambdaQuery()
                .page(new Page<>(pageNum, pageSize));

        // 使用PageVO工具类将分页结果转换为VO对象
        return PageVO.of(page, robot -> BeanUtils.copyProperties(robot, RobotVO.class));
    }

    @Override
    public RobotDetailVO getRobotStatus(Long robotId) {
        Robot robot = getById(robotId);
        if (robot == null) {
            throw new BusinessException(ROBOT_NOT_FOUND);
        }

        RobotDetailVO robotDetailVO = BeanUtils.copyProperties(robot, RobotDetailVO.class);

        // 获取机器人关联的警情ID列表
        List<Long> alertIds = alertClient.getAlertIdsByRobotId(robotId).getData();
        if (CollUtils.isEmpty(alertIds)) {
//            robotDetailVO.setAlert(new ArrayList<>());
            return robotDetailVO;
        }

        // 查询警情详情
        List<AlertDetailVO> alerts = new ArrayList<>();
        for (Long alertId : alertIds) {
            Result<?> alertResult = alertClient.getAlertDetail(alertId, false);
            if (alertResult.getCode() == 200 && alertResult.getData() != null) {
                alerts.add((AlertDetailVO) alertResult.getData());
            }
        }

        robotDetailVO.setAlert(alerts);

        return robotDetailVO;
    }
    @Override
    public void createRobot(RobotCreateDTO robotCreateDTO) {
        Robot robot = BeanUtils.copyProperties(robotCreateDTO, Robot.class);
        robot.setStatus(IDLE);
        robot.setBatteryLevel(100);
        robot.setLastActiveTime(LocalDateTime.now());
        robot.setCreatedTime(LocalDateTime.now());
        robot.setUpdatedTime(LocalDateTime.now());

        save(robot);
    }

    @Override
    public List<RobotVO> getLowBatteryRobots() {
        return lambdaQuery()
                .lt(Robot::getBatteryLevel, 30)
                .list()
                .stream()
                .map(robot -> {
                    RobotVO robotVO = BeanUtils.copyProperties(robot, RobotVO.class);
                    return robotVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<RobotVO> getRobotsByIds(List<Long> robotIds) {
        if (CollUtils.isEmpty(robotIds)) {
            return Collections.emptyList();
        }

        List<RobotVO> robots = list(Wrappers.<Robot>lambdaQuery()
                .in(Robot::getId, robotIds))
                .stream()
                .map(robot -> BeanUtils.copyProperties(robot, RobotVO.class))
                .collect(Collectors.toList());

        return robots;
    }

    @Override
    public RobotOverviewVO getRobotOverview() {
        // 获取所有机器人数据
        List<Robot> robots = this.list();

        // 统计各状态机器人数量
        Map<RobotStatus, Integer> statusDistribution = robots.stream()
                .collect(Collectors.groupingBy(
                        Robot::getStatus,
                        Collectors.collectingAndThen(Collectors.counting(), Long::intValue)
                ));

        // 构建机器人详细信息列表
        List<RobotDetailVO> robotDetailList = robots.stream()
                .map(robot -> BeanUtils.copyProperties(robot, RobotDetailVO.class))
                .collect(Collectors.toList());

        // 构建并返回概览VO
        return RobotOverviewVO.builder()
                .statusDistribution(statusDistribution)
                .robotList(robotDetailList)
                .build();
    }

    @Override
    public List<RobotStatusDistributionVO> getRobotStatusDistribution() {
        // 获取所有机器人
        List<Robot> robots = this.list();

        // 按状态分组统计数量
        Map<RobotStatus, Long> statusCountMap = robots.stream()
                .collect(Collectors.groupingBy(Robot::getStatus, Collectors.counting()));

        // 计算总数
        int totalCount = robots.size();

        // 构建分布数据
        return Arrays.stream(RobotStatus.values())
                .map(status -> {
                    long count = statusCountMap.getOrDefault(status, 0L);

                    // 计算百分比（保留2位小数）
                    BigDecimal percentage = totalCount == 0 ? BigDecimal.ZERO :
                            BigDecimal.valueOf(count)
                                    .divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP)
                                    .multiply(BigDecimal.valueOf(100));

                    return RobotStatusDistributionVO.builder()
                            .status(status.getValue())
                            .count(Math.toIntExact(count))
                            .percentage(percentage)
                            .build();
                })
                .collect(Collectors.toList());
    }

    @Override
    public PageVO<RobotVO> queryIdleRobots(Integer page, Integer size, String name) {
        // 构建查询条件
        LambdaQueryWrapper<Robot> wrapper = Wrappers.lambdaQuery(Robot.class)
                .eq(Robot::getStatus, RobotStatus.IDLE)  // 待机状态
                .gt(Robot::getBatteryLevel, 30)
                .like(StringUtils.hasText(name), Robot::getRobotName, name)  // 添加 name 模糊查询
                .orderByDesc(Robot::getLastActiveTime)   // 按最后活动时间降序
                .orderByDesc(Robot::getBatteryLevel);    // 电池电量降序

        // 执行分页查询
        Page<Robot> robotPage = this.page(new Page<>(page, size), wrapper);

        // 转换为VO对象并返回
        return PageVO.of(robotPage, robot -> BeanUtils.copyProperties(robot, RobotVO.class));
    }


    /**
     * 检查状态转换是否合法
     */
    private void checkStatusTransition(RobotStatus currentStatus, RobotStatus targetStatus) {
        // 机器人处于离线状态时，只能切换到待机状态
        if (RobotStatus.OFFLINE.equals(currentStatus) && !IDLE.equals(targetStatus)) {
            throw new BusinessException(ROBOT_NOT_IDLE_STATUS);
        }

        // 机器人正在执行任务时，不能直接切换到充电状态
//        if (RobotStatus.WORKING.equals(currentStatus)) {
//            throw new BusinessException(ROBOT_NOT_CHARGING_STATUS);
//        }
    }

    @Override
    public void updateRobotStatus(Long id, RobotStatus robotStatus) {
        // 查询机器人是否存在
        Robot robot = this.getById(id);
        if (robot == null) {
            throw new BusinessException(ROBOT_NOT_FOUND);
        }

        // 状态检查和业务规则
        checkStatusTransition(robot.getStatus(), robotStatus);

        // 更新状态
        Robot updateRobot = Robot.builder()
                .id(id)
                .status(robotStatus)
                .lastActiveTime(LocalDateTime.now())
                .build();

        // 如果状态变更为充电，重置电池电量
//        if (RobotStatus.CHARGING.equals(robotStatus)) {
//            updateRobot.setBatteryLevel(100);
//            updateRobot.setStatus(IDLE);
//        }

        boolean success = this.updateById(updateRobot);
        if (!success) {
            throw new BusinessException(ROBOT_UPDATE_STATUS_FAILED);
        }
    }

    @Override
    public Integer getRobotCount(RobotStatus status, Integer batteryThreshold) {

        LambdaQueryWrapper<Robot> queryWrapper = Wrappers.lambdaQuery(Robot.class);

        // 如果指定了状态，添加状态过滤条件
        if (status != null) {
            queryWrapper.eq(Robot::getStatus, status);
        }

        // 如果指定了电量阈值，添加电量过滤条件
        if (batteryThreshold != null) {
            queryWrapper.lt(Robot::getBatteryLevel, batteryThreshold);
        }

        // 如果两个参数都未提供，默认查询在线机器人数量（兼容原有逻辑）
        if (status == null && batteryThreshold == null) {
            queryWrapper.eq(Robot::getStatus, RobotStatus.IDLE);
        }

        List<Robot> robots = list(queryWrapper);
        return robots.size();
    }

    @Override
    public void chargeRobot(Long id, Integer batteryLevel) {
        // 检查机器人是否存在
        Robot robot = getById(id);
        if (robot == null) {
            throw new BusinessException(ROBOT_NOT_FOUND);
        }

        // 检查状态是否允许
        if (!RobotStatus.IDLE.equals(robot.getStatus()) && batteryLevel == 100) {
            throw new BusinessException(ROBOT_NOT_IDLE_STATUS);
        }

        if (batteryLevel == 100){
            lambdaUpdate()
                    .eq(Robot::getId, id)
                    .set(Robot::getBatteryLevel, 100)
                    .set(Robot::getLastActiveTime, LocalDateTime.now())
                    .set(Robot::getUpdatedTime, LocalDateTime.now())
                    .update();  // 直接调用update()执行更新
        }else{
            // 电量减去batteryLevel，这里需要判断一下，如果电量减到小于等于0，则设置为0，状态设置为离线
            if (robot.getBatteryLevel() - batteryLevel <= 0) {
                lambdaUpdate()
                        .eq(Robot::getId, id)
                        .set(Robot::getBatteryLevel, 0)
                        .set(Robot::getStatus, RobotStatus.OFFLINE)
                        .set(Robot::getLastActiveTime, LocalDateTime.now())
                        .set(Robot::getUpdatedTime, LocalDateTime.now())
                        .update();
            }
            else{
                lambdaUpdate()
                        .eq(Robot::getId, id)
                        .setSql("battery_level = battery_level - " + batteryLevel)
                        .set(Robot::getLastActiveTime, LocalDateTime.now())
                        .set(Robot::getUpdatedTime, LocalDateTime.now())
                        .update();
            }
        }
    }

    @Override
    public Long getAlertIdsByRobotId(Long robotId) {
        Robot robot = getById(robotId);
        if (robot == null) {
            throw new BusinessException(ROBOT_NOT_FOUND);
        }

//        RobotDetailVO robotDetailVO = BeanUtils.copyProperties(robot, RobotDetailVO.class);

        // 获取机器人关联的警情ID列表
        List<Long> alertIds = alertClient.getAlertIdsByRobotId(robotId).getData();

        // 查询警情详情
        AlertDetailVO alertDetailVO = new AlertDetailVO();
        for (Long alertId : alertIds) {
            Result<AlertDetailVO> alertResult = alertClient.getAlertDetail(alertId, false);
            if (alertResult.getCode() == 200 && alertResult.getData() != null && alertResult.getData().getStatus() == PROCESSING) {
                BeanUtils.copyProperties(alertResult.getData(), alertDetailVO);
            }
        }

        return alertDetailVO.getId();
    }

    @Override
    public void updateRobotLocation(Long robotId, String location) {
        lambdaUpdate()
                .eq(Robot::getId, robotId)
                .set(Robot::getLocation, location)
                .set(Robot::getLastActiveTime, LocalDateTime.now())
                .set(Robot::getUpdatedTime, LocalDateTime.now())
                .update();
    }

    @Override
    public BatteryDistributionVO getBatteryDistribution() {
        // 查询所有机器人
        List<Robot> robots = list();

        // 初始化 DTO
        BatteryDistributionVO vo = new BatteryDistributionVO();
        List<String> ranges = new ArrayList<>();
        List<Integer> counts = new ArrayList<>();

        // 预定义所有区间
        String[] allRanges = {"0-20%", "20-40%", "40-60%", "60-80%", "80-100%"};
        int[] countArray = new int[5];  // 默认值为 0

        // 如果没有数据，直接返回空结果
        if (robots == null || robots.isEmpty()) {
            for (String range : allRanges) {
                ranges.add(range);
                counts.add(0);
            }
            vo.setRanges(ranges);
            vo.setCounts(counts);
            return vo;
        }

        // 统计每个区间的机器人数量
        for (Robot robot : robots) {
            int battery = robot.getBatteryLevel();
            if (battery <= 20) {
                countArray[0]++;
            } else if (battery <= 40) {
                countArray[1]++;
            } else if (battery <= 60) {
                countArray[2]++;
            } else if (battery <= 80) {
                countArray[3]++;
            } else {
                countArray[4]++;
            }
        }

        // 填充结果
        Collections.addAll(ranges, allRanges);
        for (int count : countArray) {
            counts.add(count);
        }

        vo.setRanges(ranges);
        vo.setCounts(counts);
        return vo;
    }
}
